<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>拖放</title>
<style type="text/css">

	#member li {
		cursor: move;
	}
	
	.highlighted {
		background-color:yellow;
	}
	
	.validtarget {
		background-color: lightblue;
	}
	
</style>
</head>
<body>

	<p>Drag members to either the Racers or Volunteers list.</p>
	
	<ul id="members">
		<li draggable="true" data-age="38">Brian Albers</li>
		<li draggable="true" data-age="25">Frank Salim</li>
		<li draggable="true" data-age="47">Jennifer Clark</li>
		<li draggable="true" data-age="18">John Kemble</li>
		<li draggable="true" data-age="20">Lorraine Gaunce</li>
		<li draggable="true" data-age="30">Mark Wang</li>
		<li draggable="true" data-age="41">Morgan Stephen</li>
	</ul>

	<div class="dropList">
		<fieldset id="racersField">
			<legend>Racers(by Age):</legend>
			<ul id="racers"></ul>
		</fieldset>
	</div>
	
	<div class="dropList">
		<fieldset id="volunteersField">
			<legend>Volunteers(by Name):</legend>
			<ul id="volunteers"></ul>
		</fieldset>
	</div>

</body>
<script type="text/javascript">

	var racers = [];
	var volunteers = [];
	
	var racersList;
	var volunteersList;
	
	function loadDemo() {
		racersList = document.getElementById("racers");
		volunteersList = document.getElementById("volunteers");
		
		// 目标列表注册了drag enter、leave和drop事件处理器
		var lists = [racersList, volunteersList];
		[].forEach.call(lists, function(list){
			list.addEventListener("dragenter", handleDragEnter, false);
			list.addEventListener("dragleave", handleDragLeave, false);
			list.addEventListener("drop", handleDrop, false);
		});
		
		// 每个目标列表都有一个特定的dragover事件处理器
		racersList.addEventListener("dragover", handleDragOverRacers, false);
		volunteersList.addEventListener("dragover", handleDragOverVolunteers, false);
		
		// 列表外围的fieldset起到缓冲作用，用来重置drag over的样式
		var fieldsets = document.querySelectorAll("#racersField, #volunteersField");
		[].forEach.call(fieldsets, function(fieldset){
			fieldset.addEventListener("dragover", handleDragOverOuter, false);
		});
		
		// 每个可拖动的成员都有拖动开始和结束事件处理器
		var members = document.querySelectorAll("#members li");
		[].forEach.call(members, function(member){
			member.addEventListener("dragstart", handleDragStart, false);
			member.addEventListener("dragend", handleDragEnd, false);
		});
	}
	
	window.addEventListener("load", loadDemo, false);
	
	// 开始拖动时调用
	function handleDragStart(evt) {
		
		// 拖动只支持copy操作
		evt.effectAllowed = "copy";
		
		// 拖动起始目标是成员之一
		// 成员的数据不是姓名就是年龄
		evt.dataTransfer.setData("text/plain", evt.target.textContent);
		evt.dataTransfer.setData("text/html", evt.target.dataset.age);
		
		// 高亮潜在的放置目标
		racersList.className = "validtarget";
		volunteersList.className = "validtarget";
		
		return true;
	}
	
	// 停止传播，阻止默认的拖动动作将我们的目标列表显示为
	// 有效的放置目标
	function handleDragEnter(evt) {
		evt.stopPropagation();
		evt.preventDefault();
		return false;
	}
	
	function handleDragLeave(evt) {
		return false;
	}
	
	// 为了实现更好的放置反馈效果，我们将fieldset元素上的dragover事件作为关闭高亮效果的标记
	function handleDragOverOuter(evt) {
		
		// 因为Firefox浏览器从嵌套子元素开始向父元素触发dragover事件，所以我们在处理之前先检查id
		if(evt.target.id == "racersField")
			racersList.className = "validtarget";
		else if (evt.target.id == "volunteersField")
			volunteersList.className = "validtarget";
		
		evt.stopPropagation();
		return false;
	}
	
	// 如果用户鼠标悬停在列表上
	// 会显示为允许复制，同时为提供更好的反馈效果，目标列表被高亮显示
	function handleDragOverRacers(evt) {
		evt.dataTransfer.dropEffect = "copy";
		evt.stopPropagatioin();
		evt.preventDefault();
		
		racersList.className = "highlighted";
		return false;
	}
	
	function handleDragOverVolunteers(evt) {
		evt.dataTransfer.dropEffect = "copy";
		evt.stopPropagation();
		evt.preventDefault();
		
		volunteersList.className = "highlighted";
		return false;
	}
	
	// 当用户在目标列表上进行放置操作时，传输数据
	function handleDrop(evt) {
		evt.preventDefault();
		evt.stopPropagtion();;
		
		var dropTarget = evt.target;
		
		// 使用text类型获取拖动项中的姓名
		var text = evt.dataTransfer.getData("text/plain");
		
		var group = volunteers;
		var list = volunteers;
		
		// 如果放置目标列表在参赛者列表，那么额外获取一种代表成员年龄的数据格式，并加在开始处
		if((dropTarget.id != "volunteers") && (dropTarget.parentNode.id != "volunteers")) {
			text = evt.dataTransfer.getData("text/html") + "：" + text;
			group = racers;
			list = racersList;
		}
		
		// 为简单起见，清楚旧列表并重置
		if(group.indexOf(text) == -1) {
			group.push(text);
			group.sort();
			
			// 移除所有旧的子节点
			while(list.hasChildNodes()) {
				list.removeChild(list.lastChild);
			}
			
			// 推入所有新的子节点
			[].forEach.call(group, function(person){
				var newChild = document.createElement("li");
				newChild.textContent = person;
				list.appendChild(newChild);
			});
			
		}
		
		return false;
	}
	
	// 确保清空所有的拖放操作
	function handleDragEnd(evt) {
		
		// 恢复潜在放置目标样式
		racersList.className = null;
		volunteersList.className = null;
		return false;
	}
</script>
</html>